package database

import (
	"context"
	"fmt"
	"sync"
	"time"

	"go.uber.org/zap"

	"ddl_checker/internal/config"
	"ddl_checker/pkg/database"
	"ddl_checker/pkg/logger"
)

var (
	instance *Manager
	once     sync.Once
)

// Manager 数据库管理器（单例模式）
type Manager struct {
	db     *database.DB
	config *config.DatabaseConfig
	mu     sync.RWMutex
}

// GetInstance 获取数据库管理器单例
func GetInstance() *Manager {
	once.Do(func() {
		instance = &Manager{}
	})
	return instance
}

// Initialize 初始化数据库连接
func (m *Manager) Initialize(cfg *config.DatabaseConfig) error {
	m.mu.Lock()
	defer m.mu.Unlock()

	if m.db != nil {
		logger.Info("数据库连接已存在，关闭旧连接")
		m.db.Close()
	}

	m.config = cfg

	// 创建数据库配置
	dbConfig := &database.Config{
		Host:            cfg.Host,
		Port:            cfg.Port,
		User:            cfg.User,
		Password:        cfg.Password,
		Database:        cfg.Database,
		SSLMode:         cfg.SSLMode,
		MaxConns:        cfg.MaxConns,
		MinConns:        cfg.MinConns,
		ConnMaxLifetime: cfg.ConnMaxLifetime,
		ConnTimeout:     cfg.ConnTimeout,
	}

	// 优先使用原生 GaussDB 驱动
	m.db = database.NewDB(dbConfig)

	// 初始化连接池（对于原生 GaussDB 驱动，这会建立连接）
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()

	if err := m.db.InitPool(ctx); err != nil {
		return fmt.Errorf("初始化数据库连接池失败: %w", err)
	}

	// 验证连接
	if err := m.ping(ctx, dbConfig); err != nil {
		return fmt.Errorf("验证数据库连接失败: %w", err)
	}

	logger.Info("数据库连接成功",
		zap.String("host", cfg.Host),
		zap.String("database", cfg.Database))
	return nil
}

// ping 内部验证连接方法，避免调用 GetDB() 产生死锁
func (m *Manager) ping(ctx context.Context, dbConfig *database.Config) error {
	if m.db == nil {
		return fmt.Errorf("数据库未初始化")
	}

	// 使用连接进行 ping
	var result int
	err := m.db.QueryRow(ctx, "SELECT 1").Scan(&result)
	if err != nil {
		return fmt.Errorf("数据库 ping 失败: %w", err)
	}
	return nil
}

// GetDB 获取数据库实例
func (m *Manager) GetDB() *database.DB {
	m.mu.RLock()
	defer m.mu.RUnlock()
	return m.db
}

// Ping 检查数据库连接
func (m *Manager) Ping(ctx context.Context) error {
	db := m.GetDB()
	if db == nil {
		return fmt.Errorf("数据库未初始化")
	}

	// 使用连接进行 ping
	var result int
	err := db.QueryRow(ctx, "SELECT 1").Scan(&result)
	if err != nil {
		return fmt.Errorf("数据库 ping 失败: %w", err)
	}
	return nil
}

// Close 关闭数据库连接
func (m *Manager) Close() {
	m.mu.Lock()
	defer m.mu.Unlock()

	if m.db != nil {
		m.db.Close()
		m.db = nil
		logger.Info("数据库连接已关闭")
	}
}

// HealthCheck 健康检查
func (m *Manager) HealthCheck(ctx context.Context) error {
	return m.Ping(ctx)
}

// Stats 获取连接池统计信息
func (m *Manager) Stats() map[string]interface{} {
	db := m.GetDB()
	if db == nil {
		return map[string]interface{}{
			"status": "未初始化",
		}
	}

	return db.Stats()
}

// Reconnect 重新连接数据库
func (m *Manager) Reconnect() error {
	m.mu.RLock()
	cfg := m.config
	m.mu.RUnlock()

	if cfg == nil {
		return fmt.Errorf("数据库配置不存在")
	}

	return m.Initialize(cfg)
}
